package org.summer.gateway.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.summer.gateway.cache.PathCacheHandler;
import org.summer.gateway.pojo.SecurityPath;
import org.summer.gateway.repoistory.SecurityPathRepository;
import reactor.core.publisher.Flux;

import java.util.List;

/**
 * 请求路径数据库访问服务器层
 *
 * @author wjj9132
 * @date 2024/9/26 15:05
 * @since 1.0
 */
@Log4j2
@Component
@RequiredArgsConstructor
public class SecurityPathService {
    private final SecurityPathRepository repository;
    private final PathCacheHandler cacheHandler;

    /**
     * 使用角色编号查找角色可用请求路径集合
     */
    public Flux<SecurityPath> findListByRoleId(Long roleId) {
        return cacheHandler.getList(roleId.toString())
                .switchIfEmpty(findListByRoleIdFromDB(roleId))
                .onErrorResume(e ->{
                    log.error("获取角色路径集合失败",e);
                    return Flux.empty();
                });
    }

    /**
     * 从数据库查找角色可以请求的路径集合
     */
    private Flux<SecurityPath> findListByRoleIdFromDB(Long roleId) {
        return  repository.selectListByRoleId(roleId)
                .collectList()
                .flatMapMany(paths -> {
                    log.debug("根据角色编号从数据库查找角色可以请求的路径集合: {}", roleId);
                    if (CollectionUtils.isEmpty(paths)) {
                        log.info("查找角色{}的路径信息为空,缓存默认集合", roleId);
                        return cacheHandler.setList(roleId.toString(), createDefaultPathList(),300L)
                                .thenMany(Flux.fromIterable(paths));
                    }
                    return cacheHandler.setList(roleId.toString(), paths)
                            .thenMany(Flux.fromIterable(paths));
                });
    }

    /**
     * 构建一个默认的路径集合,集合中值包含默认的路径元素,为了查找时不频繁访问数据库
     */
    private List<SecurityPath> createDefaultPathList(){
        SecurityPath defaultPath = new SecurityPath();
        defaultPath.setPattern("/");
        defaultPath.setMethod("GET");
        return List.of(defaultPath);
    }
}
